﻿/// ****************************************************************************
/// Author:	        Robin Zhu
/// Create Date:	2013-4-15
/// Purpose: 		数据操作执行类（SQLite版本）文件
/// ****************************************************************************
/// Modify By		Date			Remark
/// ****************************************************************************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Data.SQLite;
using System.Reflection;

namespace RB.DataAccess.SQLite
{
    /// <summary>
    /// 数据操作执行类（Microsoft SQL Server版本）
    /// </summary>
    public class SQLiteExecutor : Executor
    {
        public SQLiteExecutor(SQLiteDataContext dataContext)
            : base(dataContext)
        {

        }

        /// <summary>
        /// 插入新记录，如果有Identity字段，则返回该字段的值
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="entity">实体对象实例</param>
        /// <param name="mappingTo">映射到另一个表，默认为空，表示使用类型T获取表名</param>
        /// <returns>插入的记录数</returns>
        public override int Insert<T>(T entity, string mappingTo)
        {
            bool ignoreAutoIncrement = TypeMapper<T>.IgnoreAutoIncrement;
            PropertyInfo identityField = null;

            bool bTrans = IsTransactionBegin();
            if (!ignoreAutoIncrement)
            {
                identityField = TypeMapper<T>.AutoIncrementField;
                if (identityField != null && !bTrans)
                    BeginTransaction();
            }
            int result = 0;
            try
            {
                result = Insert<T, T>(p => entity, mappingTo);

                if (identityField != null)
                {
                    object oid = ExecuteScalar("SELECT last_insert_rowid()");
                    int id = Convert.ToInt32(oid);
                    identityField.SetValue(entity, id, null);

                    if (!bTrans)
                        CommitTransaction();
                }
            }
            catch
            {
                if (identityField != null && !bTrans)
                    RollbackTransaction();
                throw;
            }
            return result;
        }

        public override int Insert<T, TFields>(Expression<Func<T, TFields>> fields, string mappingTo)
        {
            //TypeMapper<T>.UseNativeAutoIncrement();

            int n = 0;
            try
            {
                n = base.Insert<T, TFields>(fields, mappingTo);
            }
            catch (SQLiteException e)
            {
                if (e.ErrorCode == (int)SQLiteErrorCode.Constraint && e.Message.Contains("PRIMARY KEY"))
                    throw new PrimaryKeyException(e);
                else
                    throw;
            }
            return n;
        }

        public override int Insert<TFields>(IQueryable<TFields> query, string mappingTo)
        {
            int n = 0;
            try
            {
                n = base.Insert<TFields>(query, mappingTo);
            }
            catch (SQLiteException e)
            {
                if (e.ErrorCode == (int)SQLiteErrorCode.Constraint && e.Message.Contains("PRIMARY KEY"))
                    throw new PrimaryKeyException(e);
                else
                    throw;
            }
            return n;
        }

        public override int Update<T, TFields>(Expression<Func<T, TFields>> fields, Expression<Func<T, bool>> predict, string mappingTo)
        {
            TypeMapper<T>.UseNativeAutoIncrement();

            int n = 0;
            try
            {
                n = base.Update<T, TFields>(fields, predict, mappingTo);
            }
            catch (SQLiteException e)
            {
                if (e.ErrorCode == (int)SQLiteErrorCode.Constraint && e.Message.Contains("PRIMARY KEY"))
                    throw new PrimaryKeyException(e);
                else
                    throw;
            }

            return n;
        }

        public override int Update<T, TFields>(Expression<Func<T, TFields>> fields, IQueryable<T> query)
        {
            TypeMapper<T>.UseNativeAutoIncrement();

            int n = 0;
            try
            {
                n = base.Update<T, TFields>(fields, query);
            }
            catch (SQLiteException e)
            {
                if (e.ErrorCode == (int)SQLiteErrorCode.Constraint && e.Message.Contains("PRIMARY KEY"))
                    throw new PrimaryKeyException(e);
                else
                    throw;
            }

            return n;
        }
    }
}
